﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace ERPStore.Models
{
	/// <summary>
	/// Definition d'un produit
	/// </summary>
	[Serializable]
	[DataContract]
	public class Product : IExtendable, ILocalizable, IModelIdentity
	{
		public Product()
		{
			Shipping = new ProductShipping();
			SaleMode = ProductSaleMode.Sellable;
			PriceByQuantityList = new List<PriceByQuantity>();
			SortPropertyDictionary = new Dictionary<string, string>();
			Stats = new ProductStats();
			Gtin = new Gtin();
			OfferList = new List<Offer>();
		}

		/// <summary>
		/// Identifiant du produit interne
		/// </summary>
		/// <value>The id.</value>
		[DataMember]
		public int Id { get; set; }
		/// <summary>
		/// Date de création du produit
		/// </summary>
		/// <value>The creation date.</value>
		[DataMember]
		public DateTime CreationDate { get; set; }
		/// <summary>
		/// Code unique du produit
		/// </summary>
		/// <value>The code.</value>
		[Searchable]
		[DataMember]
		public string Code { get; set; }
		/// <summary>
		/// Titre du produit
		/// </summary>
		/// <value>The title.</value>
		[Searchable]
		[DataMember]
		public string Title { get; set; }
		/// <summary>
		/// Description courte , normalement pas plus de 2 lignes
		/// </summary>
		/// <value>The short description.</value>
		[Searchable]
		[DataMember]
		public string ShortDescription { get; set; }
		/// <summary>
		/// Description longue (pas de limite de longueur) peut contenir du texte en html
		/// </summary>
		/// <value>The long description.</value>
		[Searchable]
		[DataMember]
		public string LongDescription { get; set; }
		/// <summary>
		/// Category à laquelle appartient le produit
		/// si la catégorie n'est pas référencée pour le site, cette valeur sera null
		/// </summary>
		/// <value>The category.</value>
		[DataMember]
		public ProductCategory Category { get; set; }
		/// <summary>
		/// Marque à laquelle appartient le produit
		/// si la marque n'est pas référencée pour le site, alors il est attaché a "Sans marque"
		/// </summary>
		/// <value>La marque, cette valeur n'est jamais nulle.</value>
		[DataMember]
		public Brand Brand { get; set; }
		/// <summary>
		/// Empaquetage du produit
		/// </summary>
		/// <value>The packaging.</value>
		[DataMember]
		public Packaging Packaging { get; set; }
		/// <summary>
		/// Unité de vente les valeurs peuvent etre 1 , 100 , 1000 ou 10000
		/// </summary>
		/// <value>The sale unit value.</value>
		[DataMember]
		public int SaleUnitValue { get; set; }
		/// <summary>
		/// Taux de taxe par defaut
		/// </summary>
		/// <value>The default tax rate.</value>
		[DataMember]
		public double DefaultTaxRate { get; set; }
		/// <summary>
		/// Liste des mots clés, utilisé comme information meta dans la page html du produit
		/// </summary>
		/// <value>The keywords.</value>
		[Searchable]
		[DataMember]
		public string Keywords { get; set; }
		/// <summary>
		/// Partie du lien vers la fiche produit
		/// </summary>
		/// <value>The link.</value>
		[DataMember]
		public string Link { get; set; }
		/// <summary>
		/// Texte sur les points forts du produit
		/// </summary>
		/// <value>The strengths points.</value>
		[Searchable]
		[DataMember]
		public string StrengthsPoints { get; set; }
		/// <summary>
		/// Url du constructeur du produit
		/// </summary>
		/// <value>The manufacturer URL.</value>
		[DataMember]
		public string ManufacturerUrl { get; set; }
		/// <summary>
		/// Poids du produit en grammes
		/// </summary>
		/// <value>The weight.</value>
		[DataMember]
		public int Weight { get; set; }
		/// <summary>
		/// Titre de la page web
		/// </summary>
		/// <remarks>
		/// Ne doit etre utilisé que dans le header de la page
		/// </remarks>
		/// <value>The page title.</value>
		[Searchable]
		[DataMember]
		public string PageTitle { get; set; }
		/// <summary>
		/// Description de la page web
		/// </summary>
		/// <remarks>
		/// Ne doit etre utilisé que dans le header de la page
		/// </remarks>
		/// <value>The page description.</value>
		[Searchable]
		[DataMember]
		public string PageDescription { get; set; }
		/// <summary>
		/// Nombre de commande, permet de trier les listes sur ce critère
		/// </summary>
		/// <value>The order count.</value>
		[DataMember]
		public int OrderCount { get; set; }
		/// <summary>
		/// Indique si le produit à du stock
		/// </summary>
		/// <value>The has stock.</value>
		[DataMember]
		public bool HasStock { get; set; }
		/// <summary>
		/// Quantité minimale de vente
		/// </summary>
		/// <value>The minimum sale quantity.</value>
		[DataMember]
		public int MinimumSaleQuantity { get; set; }

		/// <summary>
		/// Image par defaut
		/// </summary>
		/// <value>The default image., s'il n'y a pas d'image, cette valeur est nulle</value>
		[DataMember]
		public Media DefaultImage { get; set; }
		/// <summary>
		/// Retourne la valeur en % de la promotion
		/// </summary>
		/// <value>The promotionnal discount.</value>
		/// <summary>
		/// Indique qu'un produit possède une image par defaut
		/// </summary>
		/// <value>
		/// 	<c>true</c> if this instance has picture; otherwise, <c>false</c>.
		/// </value>
		public bool HasPicture 
		{
			get
			{
				return DefaultImage != null;
			}
		}

		/// <summary>
		/// Nombre d'image pour le produit
		/// </summary>
		[DataMember]
		public int? ImageCount { get; set; }

		/// <summary>
		/// Nombre de document attachés
		/// </summary>
		[DataMember]
		public int? DocumentCount { get; set; }

		/// <summary>
		/// Liste des propriétés etendues 
		/// </summary>
		/// <value>The extended properties.</value>
		[IgnoreDataMember]
		public ExtendedPropertyList ExtendedProperties { get; set; }

		/// <summary>
		/// Unité du produit (metre, kilogramme, temps, unité)
		/// </summary>
		/// <value>The metric.</value>
		[DataMember]
		public Metric Metric { get; set; }

		/// <summary>
		/// Liste des propriétés de type string traduites
		/// </summary>
		/// <value>The localization list.</value>
		public IEnumerable<EntityLocalization> LocalizationList { get; set; }

		/// <summary>
		/// Dernière modification sur le produit
		/// </summary>
		/// <value>The last update.</value>
		[DataMember]
		public DateTime LastUpdate { get; set; }

		/// <summary>
		/// Paramètre de calcul des frais de port
		/// </summary>
		/// <value>The transport.</value>
		[DataMember]
		public ProductShipping Shipping { get; private set; }

		/// <summary>
		/// Mode de vente du produit
		/// </summary>
		/// <value>The sale mode.</value>
		[DataMember]
		public ProductSaleMode SaleMode { get; set; }

		public bool IsSellable
		{
			get
			{
				if (SaleMode != ProductSaleMode.Sellable)
				{
					return false;
				}
				return true;
			}
		}

		/// <summary>
		/// Type de tarification
		/// </summary>
		public PriceType PriceType { get; set; }

		/// <summary>
		/// Liste de prix de vente en fonction d'interval de quantité
		/// </summary>
		/// <value>The price by quantity list.</value>
		[DataMember]
		public List<PriceByQuantity> PriceByQuantityList { get; private set; }

		/// <summary>
		/// Niveau de stockage du produit
		/// </summary>
		/// <value>The storage rank.</value>
		[DataMember]
		public ProductStorageRank? StorageRank { get; set; }

		/// <summary>
		/// Designe la garantie du produit, le texte est libre
		/// </summary>
		/// <value>The warranty.</value>
		[DataMember]
		public string Warranty { get; set; }

		/// <summary>
		/// Liste de valeurs de tri supplémentaires
		/// </summary>
		[IgnoreDataMember]
		public Dictionary<string, string> SortPropertyDictionary { get; private set; }

		/// <summary>
		/// Statistique sur le produit
		/// </summary>
		public ProductStats Stats { get; private set; }

		/// <summary>
		/// Liste de codes produits unique identifiant le produit
		/// dans divers pays
		/// 
		/// Global Trade Item Number
		/// </summary>
		[DataMember]
		public Gtin Gtin { get; set; }

		/// <summary>
		/// Identifiant du fabricant
		/// </summary>
		[DataMember]
		public string ManufacturerPartNumber { get; set; }

		/// <summary>
		/// Identifiant du produit de type variation parent
		/// </summary>
		[DataMember]
		public int? VariationProductParentId { get; set; }

		/// <summary>
		/// Produit de type Variation Parent
		/// </summary>
		[DataMember]
		public bool IsParentVariation { get; set; }

		/// <summary>
		/// Indique que le produit est une composition de plusieurs produits
		/// </summary>
		[DataMember]
		public bool IsPack { get; set; }

		/// <summary>
		/// Liste des offres possibles
		/// </summary>
		[DataMember]
		public List<Offer> OfferList { get; set; }

		/// <summary>
		/// Remise sur le tarif de base du produit
		/// est calculé par les offres
		/// </summary>
		public double? Discount { get; set; }

		#region Prices

		/// <summary>
		/// Prix de vente du produit
		/// </summary>
		/// <value>The sale price.</value>
		[DataMember]
		public Price SalePrice { get; set; }
		/// <summary>
		/// Montant de l'eco taxe
		/// </summary>
		/// <value>The recycle price.</value>
		[DataMember]
		public Price RecyclePrice { get; set; }
		/// <summary>
		/// Meilleur prix pratiqué (le plus bas)
		/// </summary>
		/// <value>The best price.</value>
		[DataMember]
		public Price BestPrice { get; set; }
		/// <summary>
		/// Montant du prix barré
		/// </summary>
		[DataMember]
		public Price StrikedPrice { get; set; }

		#endregion

		/// <summary>
		/// Type de prix selectionné pour avoir le meilleur prix
		/// </summary>
		/// <value>The selected price.</value>
		[DataMember]
		public Offer SelectedOffer { get; set; }

		[IgnoreDataMember]
		public object Tag { get; set; }
	}
}
